package headerparser

import (
	"errors"
	"net/http"
	"reflect"
)

var (
	ErrTarget     = errors.New("target should be a non-nil pointer")
	ErrTargetElem = errors.New("element of target should be a struct")
)

func Parse(h http.Header, target interface{}) error {
	if target == nil {
		return ErrTarget
	}
	v := reflect.ValueOf(target)
	if v.Kind() != reflect.Ptr {
		return ErrTarget
	}
	vElem := v.Elem()
	if vElem.Kind() != reflect.Struct {
		return ErrTargetElem
	}
	tElem := vElem.Type()
	for i, nf := 0, tElem.NumField(); i < nf; i++ {
		f := tElem.Field(i)
		key := f.Tag.Get("header")
		value := h.Values(key)
		if len(value) == 0 {
			continue
		}
		// 假如结构体中的目标字段是个切片，则逐个解析，否则只解析 value[0]
		if f.Type.Kind() == reflect.Slice {
			if fn, ok := sliceParseFuncs[f.Type.String()]; ok {
				if parsedValue, err := fn(value); err == nil {
					// 这里是整个切片覆盖赋值，所以 parsedValue 必须和 vElem.Field(i) 类型一样
					if reflect.TypeOf(parsedValue).ConvertibleTo(f.Type) {
						vElem.Field(i).Set(reflect.ValueOf(parsedValue))
					}
				}
			}
			continue
		}

		if fn, ok := parseFuncs[f.Type.String()]; ok {
			if parsedValue, err := fn(value[0]); err == nil {
				if reflect.TypeOf(parsedValue).ConvertibleTo(f.Type) {
					vElem.Field(i).Set(reflect.ValueOf(parsedValue))
				}
			}
		}
	}
	return nil
}
